/**
 * @p.md
 * 
 * 持久化上下文的具体实现
 */
import { Context } from '../actor/context';
import { ActorSystem } from '../actor/actorSystem';
import { PID } from '../actor/pid';
import { Props } from '../actor/props';
import { Future } from '../actor/future';
import { Actor } from '../actor/actor';
import { 
  CommandContext, 
  EventSelectionCriteria, 
  EventType, 
  PersistentContext, 
  RecoverContext, 
  SnapshotSelectionCriteria 
} from './persistent';
import { PersistenceProvider } from './persistenceProvider';

/**
 * 持久化上下文的基础实现
 */
export class DefaultPersistentContext implements PersistentContext {
  private _actor: Actor;
  private _self: PID;
  private _children: Map<string, PID>;
  private _sender?: PID;
  private _message: any;
  private _parent?: PID;
  private _receiveTimeout: number = 0;
  protected _stash: any[] = [];
  protected _watched: Set<string> = new Set<string>();

  /**
   * 构造函数
   * @param _actorSystem Actor 系统
   * @param persistenceProvider 持久化提供者
   * @param persistenceId 持久化 ID
   * @param actor Actor 实例
   * @param self 当前 Actor 的 PID
   * @param message 当前消息
   * @param parent 父 Actor 的 PID
   */
  constructor(
    protected readonly _actorSystem: ActorSystem,
    protected readonly persistenceProvider: PersistenceProvider,
    protected readonly persistenceId: string,
    actor: Actor,
    self: PID,
    message: any,
    parent?: PID
  ) {
    this._actor = actor;
    this._self = self;
    this._children = new Map<string, PID>();
    this._message = message;
    this._parent = parent;
  }

  /**
   * 获取当前 Actor 系统
   */
  actorSystem(): ActorSystem {
    return this._actorSystem;
  }

  /**
   * 获取当前消息
   */
  message(): any {
    return this._message;
  }

  /**
   * 获取当前 Actor 的 PID
   */
  self(): PID {
    return this._self;
  }

  /**
   * 获取消息发送者的 PID
   */
  sender(): PID | undefined {
    return this._sender;
  }

  /**
   * 设置消息发送者的 PID
   * @param pid 发送者 PID
   */
  setSender(pid?: PID): void {
    this._sender = pid;
  }

  /**
   * 获取父 Actor 的 PID
   */
  parent(): PID | null {
    return this._parent || null;
  }

  /**
   * 获取当前 Actor
   */
  actor(): Actor {
    return this._actor;
  }

  /**
   * 获取接收超时时间
   */
  receiveTimeout(): number {
    return this._receiveTimeout;
  }

  /**
   * 设置接收超时时间
   * @param duration 超时时间（毫秒）
   */
  setReceiveTimeout(duration: number): void {
    this._receiveTimeout = duration;
  }

  /**
   * 取消接收超时设置
   */
  cancelReceiveTimeout(): void {
    this._receiveTimeout = 0;
  }

  /**
   * 获取子 Actor 列表
   */
  children(): PID[] {
    return Array.from(this._children.values());
  }

  /**
   * 将当前消息存入暂存区
   */
  stash(): void {
    this._stash.push(this._message);
  }

  /**
   * 监视指定的 Actor
   * @param pid 要监视的 Actor 的 PID
   */
  watch(pid: PID): void {
    const key = `${pid.address}/${pid.id}`;
    this._watched.add(key);
    // 实际实现应该通知目标 Actor
  }

  /**
   * 取消监视指定的 Actor
   * @param pid 要取消监视的 Actor 的 PID
   */
  unwatch(pid: PID): void {
    const key = `${pid.address}/${pid.id}`;
    this._watched.delete(key);
    // 实际实现应该通知目标 Actor
  }

  /**
   * 将当前消息转发给指定的 Actor
   * @param target 目标 Actor 的 PID
   */
  forward(target: PID): void {
    this._actorSystem.root.send(target, this._message);
  }

  /**
   * 在 Future 完成后重新进入 Actor 处理
   * @param future 等待的 Future
   * @param continuation 完成后的回调函数
   */
  reenterAfter(future: Future<any>, continuation: (result: any, error: Error | null) => void): void {
    // 使用 async/await 处理 Future 结果
    (async () => {
      try {
        // 等待 Future 完成并获取结果
        const result = await future.result();
        continuation(result, null);
      } catch (error) {
        continuation(null, error as Error);
      }
    })();
  }

  /**
   * 向指定 Actor 发送消息
   * @param target 目标 Actor 的 PID
   * @param message 消息
   */
  send(target: PID, message: any): void {
    this._actorSystem.root.send(target, message);
  }

  /**
   * 向指定 Actor 发送请求
   * @param target 目标 Actor 的 PID
   * @param message 消息
   */
  request(target: PID, message: any): void {
    this._actorSystem.root.request(target, message);
  }

  /**
   * 向指定 Actor 发送请求并返回 Future
   * @param target 目标 Actor 的 PID
   * @param message 消息
   * @param timeout 超时时间
   */
  requestFuture(target: PID, message: any, timeout: number): Future<any> {
    return this._actorSystem.root.requestFuture(target, message, timeout);
  }

  /**
   * 生成响应
   * @param message 响应消息
   */
  respond(message: any): void {
    if (this._sender) {
      this.send(this._sender, message);
    }
  }

  /**
   * 创建新 Actor
   * @param props 属性
   */
  spawn(props: Props): PID {
    return this._actorSystem.root.spawn(props);
  }

  /**
   * 使用指定名称创建新 Actor
   * @param props 属性
   * @param name 名称
   */
  spawnNamed(props: Props, name: string): PID {
    return this._actorSystem.root.spawnNamed(props, name);
  }

  /**
   * 使用指定前缀创建新 Actor
   * @param props 属性
   * @param prefix 前缀
   */
  spawnPrefix(props: Props, prefix: string): PID {
    return this._actorSystem.root.spawnPrefix(props, prefix);
  }

  /**
   * 生成子 Actor
   * @param props 属性
   * @param name 名称
   */
  spawnChild(props: Props, name?: string): PID {
    const pid = name 
      ? this._actorSystem.root.spawnNamed(props, `${this._self.id}/${name}`)
      : this._actorSystem.root.spawnPrefix(props, `${this._self.id}/`);
    
    if (name) {
      this._children.set(name, pid);
    }
    return pid;
  }

  /**
   * 停止子 Actor
   * @param pid 子 Actor 的 PID
   */
  stopChild(pid: PID): void {
    this.stopActor(pid);
    // 从子 Actor 列表中移除
    for (const [name, childPid] of this._children.entries()) {
      if (childPid.id === pid.id && childPid.address === pid.address) {
        this._children.delete(name);
        break;
      }
    }
  }

  /**
   * 停止任意 Actor
   * @param pid 要停止的 Actor 的 PID
   */
  stop(pid: PID): void {
    this.stopActor(pid);
  }
  
  /**
   * 内部方法：停止 Actor
   * @param pid 要停止的 Actor 的 PID
   * @private
   */
  private stopActor(pid: PID): void {
    this._actorSystem.root.stop(pid);
  }

  /**
   * 停止自己
   */
  stopSelf(): void {
    this._actorSystem.root.stop(this._self);
  }

  /**
   * 向所有子 Actor 发送消息
   * @param message 消息
   */
  sendToChildren(message: any): void {
    for (const pid of this._children.values()) {
      this.send(pid, message);
    }
  }

  /**
   * 持久化事件
   * @param event 事件
   */
  async persist(event: any): Promise<void> {
    // 这里应该获取下一个索引号
    const index = await this.getNextIndex();
    return this.persistenceProvider.persistEvent(this.persistenceId, index, event);
  }

  /**
   * 批量持久化事件
   * @param events 事件数组
   */
  async persistAll(events: any[]): Promise<void> {
    let index = await this.getNextIndex();
    for (const event of events) {
      await this.persistenceProvider.persistEvent(this.persistenceId, index, event);
      index++;
    }
  }

  /**
   * 创建快照
   * @param snapshot 快照数据
   */
  async snapshot(snapshot: any): Promise<void> {
    const index = await this.getNextIndex();
    return this.persistenceProvider.persistSnapshot(this.persistenceId, index, snapshot);
  }

  /**
   * 删除快照
   * @param criteria 选择条件
   */
  async deleteSnapshots(criteria: SnapshotSelectionCriteria): Promise<void> {
    return this.persistenceProvider.deleteSnapshots(
      this.persistenceId, 
      criteria.minSequenceNr, 
      criteria.maxSequenceNr
    );
  }

  /**
   * 删除事件
   * @param criteria 选择条件
   */
  async deleteEvents(criteria: EventSelectionCriteria): Promise<void> {
    return this.persistenceProvider.deleteEvents(
      this.persistenceId, 
      criteria.minSequenceNr, 
      criteria.maxSequenceNr
    );
  }

  /**
   * 获取下一个索引值
   * @private
   */
  private async getNextIndex(): Promise<number> {
    // 获取最近的事件并返回其索引+1
    const events = await this.persistenceProvider.getEventsByPersistenceId(
      this.persistenceId, 
      0, 
      Number.MAX_SAFE_INTEGER
    );
    
    return events.length > 0 ? events[events.length - 1].index + 1 : 0;
  }
}

/**
 * 恢复上下文实现
 */
export class DefaultRecoverContext extends DefaultPersistentContext implements RecoverContext {
  readonly event: any;
  readonly eventType: EventType;
  readonly eventIndex: number;

  /**
   * 构造函数
   */
  constructor(
    actorSystem: ActorSystem,
    persistenceProvider: PersistenceProvider,
    persistenceId: string,
    actor: Actor,
    self: PID,
    event: any,
    eventType: EventType,
    eventIndex: number,
    parent?: PID
  ) {
    super(actorSystem, persistenceProvider, persistenceId, actor, self, event, parent);
    this.event = event;
    this.eventType = eventType;
    this.eventIndex = eventIndex;
  }
}

/**
 * 命令上下文实现
 */
export class DefaultCommandContext extends DefaultPersistentContext implements CommandContext {
  readonly index: number;

  /**
   * 构造函数
   */
  constructor(
    actorSystem: ActorSystem,
    persistenceProvider: PersistenceProvider,
    persistenceId: string,
    actor: Actor,
    self: PID,
    message: any,
    index: number,
    parent?: PID
  ) {
    super(actorSystem, persistenceProvider, persistenceId, actor, self, message, parent);
    this.index = index;
  }
} 